package meter

import (
	"context"
	"fmt"
	"strconv"
	"strings"

	"github.com/gogf/gf/v2/frame/g"
)

// EleRechargeRequest represents the request parameters for electrical meter recharge API
// EleRechargeRequest 表示电表充值API的请求参数
type EleRechargeRequest struct {
	Address   string `json:"address" v:"required"`   // 设备列表的address
	CID       string `json:"cid" v:"required"`       // 设备列表的cid
	AccountId string `json:"accountId" v:"required"` // 账户ID
	Money     string `json:"money" v:"required"`     // 充值金额
	Count     string `json:"count" v:"required"`     // 数据库记录计数
	Price     string `json:"price" v:"required"`     // 单价，数字字符串格式，例如：1块钱/kwh
}

// EleRechargeResponse represents the complete response from electrical meter recharge API
// EleRechargeResponse 表示电表充值API的完整响应
type EleRechargeResponse struct {
	Code    int              `json:"code"`    // 响应状态码
	Message string           `json:"message"` // 响应消息
	Data    *EleRechargeData `json:"data"`
}

type EleRechargeData struct {
	Data        any    `json:"data"`
	ErrMsg      string `json:"err_msg"`
	OprId       string `json:"opr_id"`
	ResolveTime string `json:"resolve_time"`
	Status      string `json:"status"` // 响应状态
}

// Validate validates the EleRechargeRequest parameters using GoFrame validation
// Validate 使用GoFrame验证EleRechargeRequest参数
func (r *EleRechargeRequest) Validate() error {
	// First validate the struct fields using GoFrame
	if err := g.Validator().Data(r).Run(context.Background()); err != nil {
		return err
	}

	// Additional validation for money amount
	if err := r.validateMoney(); err != nil {
		return err
	}

	// Additional validation for count parameter
	if err := r.validateCount(); err != nil {
		return err
	}

	// Additional validation for address and cid format
	if err := r.validateDeviceIdentifiers(); err != nil {
		return err
	}

	return nil
}

// validateMoney validates the money field to ensure it's a positive decimal number
func (r *EleRechargeRequest) validateMoney() error {
	if strings.TrimSpace(r.Money) == "" {
		return fmt.Errorf("money cannot be empty")
	}

	// Parse money as float to validate format
	amount, err := strconv.ParseFloat(r.Money, 64)
	if err != nil {
		return fmt.Errorf("money must be a valid decimal number: %v", err)
	}

	// Check if amount is positive
	if amount <= 0 {
		return fmt.Errorf("money amount must be positive, got: %f", amount)
	}

	// Check reasonable limits (minimum 0.01, maximum 10000)
	if amount < 0.01 {
		return fmt.Errorf("money amount too small, minimum is 0.01, got: %f", amount)
	}
	if amount > 10000 {
		return fmt.Errorf("money amount too large, maximum is 10000, got: %f", amount)
	}

	return nil
}

// validateCount validates the count field to ensure it's a valid numeric string
func (r *EleRechargeRequest) validateCount() error {
	if strings.TrimSpace(r.Count) == "" {
		return fmt.Errorf("count cannot be empty")
	}

	// Parse count as integer to validate format
	count, err := strconv.ParseInt(r.Count, 10, 64)
	if err != nil {
		return fmt.Errorf("count must be a valid integer: %v", err)
	}

	// Check if count is non-negative
	if count < 0 {
		return fmt.Errorf("count must be non-negative, got: %d", count)
	}

	return nil
}

// validateDeviceIdentifiers validates address and cid format
func (r *EleRechargeRequest) validateDeviceIdentifiers() error {
	// Validate address format (should be numeric string)
	if strings.TrimSpace(r.Address) == "" {
		return fmt.Errorf("address cannot be empty")
	}
	if _, err := strconv.ParseInt(r.Address, 10, 64); err != nil {
		return fmt.Errorf("address must be a valid numeric string: %v", err)
	}

	// Validate cid format (should be numeric string)
	if strings.TrimSpace(r.CID) == "" {
		return fmt.Errorf("cid cannot be empty")
	}
	if _, err := strconv.ParseInt(r.CID, 10, 64); err != nil {
		return fmt.Errorf("cid must be a valid numeric string: %v", err)
	}

	// Validate accountId is not empty
	if strings.TrimSpace(r.AccountId) == "" {
		return fmt.Errorf("accountId cannot be empty")
	}

	return nil
}
